package cn.italkcloud.cph.controller;

import cn.italkcloud.cph.config.exception.BusinessException;
import cn.italkcloud.cph.config.sys.Response;
import cn.italkcloud.cph.constants.enums.FailedEnum;
import cn.italkcloud.cph.constants.enums.PermDataEnum;
import cn.italkcloud.cph.constants.enums.vos.CustomerTypeEnum;
import cn.italkcloud.cph.constants.enums.vos.FeeLogTypeEnum;
import cn.italkcloud.cph.entity.VosCustomer;
import cn.italkcloud.cph.entity.VosCustomerGroup;
import cn.italkcloud.cph.entity.VosFeeLog;
import cn.italkcloud.cph.entity.VosServer;
import cn.italkcloud.cph.entity.dto.*;
import cn.italkcloud.cph.entity.dto.vos.CallDetailDTO;
import cn.italkcloud.cph.entity.dto.vos.PayDTO;
import cn.italkcloud.cph.entity.req.*;
import cn.italkcloud.cph.entity.wrapper.VosWrapper;
import cn.italkcloud.cph.helper.RequestCacheHelper;
import cn.italkcloud.cph.helper.VosHelper;
import cn.italkcloud.cph.service.*;
import cn.italkcloud.cph.utils.BaseUtil;
import cn.italkcloud.cph.utils.StringUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author dominate
 * @since 2022/11/21 10:53
 */
@RestController
@RequestMapping("/vos")
public class VosController extends BaseController {


    @Resource
    private VosService vosService;
    @Resource
    private IVosServerService vosServerService;
    @Resource
    private IVosCustomerService vosCustomerService;
    @Resource
    private IVosCustomerGroupService vosCustomerGroupService;
    @Resource
    private IVosGroupRelateService vosGroupRelateService;

    @Resource
    private IVosFeeLogService vosFeeLogService;


    @PostMapping("/checkServer")
    public Response<VosServerCheckDTO> checkServer(@RequestBody CheckVosServerReq req) {
        VosServerCheckDTO checkResult = new VosServerCheckDTO();
        if (StringUtil.isNotBlank(req.getApiUrl())) {
            checkResult.setApiUrl(req.getApiUrl());
            checkResult.setApiConnection(VosHelper.checkServerApiConnection(req.getApiUrl()));
        }
        if (StringUtil.isNotBlank(req.getMysqlUser())) {
            checkResult.setMysqlUrl(req.getMysqlUser());
            checkResult.setMysqlConnection(VosHelper.checkServerMysqlConnection(req.getMysqlUrl(), req.getMysqlUser(), req.getMysqlPassword()));
        }
        return Response.data(checkResult);
    }

    @PostMapping("/getServer")
    public Response<List<VosServerDTO>> getServer(@RequestBody GetVosServerReq req) {
        // 查询其他账户客户数据需要权限
        int accountId = getAccountId();
        if (Objects.nonNull(req.getAccountId())) {
            if (PermDataEnum.SHOW_ALL_VOS_SERVER.verify(getToken())) {
                accountId = req.getAccountId();
            }
        }
        List<VosServer> serverList = vosServerService.query(accountId, req.getName(), req.isForList());
        return Response.data(VosWrapper.builder().entityServerDTO(serverList));
    }

    @PostMapping("/modifyServer")
    public Response<Boolean> modifyServer(@RequestBody ModifyVosServerReq req) {
        // 修改时检测归属，不是该全用户的检测下权限
        if (Objects.nonNull(req.getId())) {
            if (!PermDataEnum.MODIFY_VOS_SERVER.verify(getToken())) {
                if (!vosServerService.isOwner(getAccountId(), req.getId())) {
                    throw BusinessException.create(FailedEnum.NEED_PERM);
                }
            }
        }
        VosServer target = new VosServer();
        BaseUtil.set(target, req);
        if (Objects.isNull(req.getId())) {
            // 新增
            int accountId = getAccountId();
            target.setAccountId(accountId);
            return Response.data(vosServerService.save(target));
        }
        if (Objects.nonNull(req.getDel()) && req.getDel()) {
            if (vosCustomerService.hasCustomer(req.getId())) {
                throw BusinessException.create(FailedEnum.CAN_NOT_DEL_VOS_SERVER);
            }
            // 删除
            return Response.data(vosServerService.removeById(req.getId()));
        }
        // 更新
        VosServer base = vosServerService.getById(req.getId());
        VosServer update = new VosServer();
        // 没有需要更新的，但是都更新了
        if (!BaseUtil.compare(base, target, update)) {
            return Response.data(true);
        }
        update.setId(target.getId());
        return Response.data(vosServerService.updateById(update));
    }

    @PostMapping("/getAllCustomer")
    public Response<List<VosCustomerDTO>> getAllCustomer(@RequestBody IdReq req) {
        if (!PermDataEnum.SHOW_ALL_CUSTOMER.verify(getToken())) {
            throw BusinessException.create(FailedEnum.NEED_PERM);
        }
        Integer serverId = req.getId();
        String apiUrl = vosServerService.getApiUrl(serverId);
        if (StringUtil.isBlank(apiUrl)) {
            throw BusinessException.create(FailedEnum.NOT_FOUND_VOS_SERVER);
        }
        // 已绑定的账户
        List<VosCustomer> customerList = vosCustomerService.getValidList(serverId);
        // 所有VOS账户
        List<String> vosAccountList = VosHelper.getAllCustomerNameList(apiUrl);
        return Response.data(VosWrapper.builder().merge(customerList, vosAccountList));
    }

    @PostMapping("/getCustomerGroupList")
    public Response<List<VosCustomerGroupDTO>> getCustomerGroupList(@RequestBody NameReq req) {
        int accountId = getAccountId();
        String name = req.getName();
        List<VosCustomerGroup> customerGroupList = vosCustomerGroupService.query(accountId, name);
        return Response.data(VosWrapper.builder().entityCustomerGroupDTO(customerGroupList));
    }

    @PostMapping("/modifyCustomerGroup")
    public Response<Boolean> modifyCustomerGroup(@RequestBody ModifyVosCustomerGroupReq req) {
        if (!PermDataEnum.MODIFY_VOS_SERVER.verify(getToken())) {
            throw BusinessException.create(FailedEnum.NEED_PERM);
        }
        VosCustomerGroup target = new VosCustomerGroup();
        BaseUtil.set(target, req);
        if (Objects.isNull(req.getId())) {
            // 新增
            int accountId = getAccountId();
            target.setAccountId(accountId);
            return Response.data(vosCustomerGroupService.save(target));
        }
        if (Objects.nonNull(req.getDel()) && req.getDel()) {
            // 删除
            return Response.data(vosCustomerGroupService.removeById(req.getId()));
        }
        // 更新
        VosCustomerGroup base = vosCustomerGroupService.getById(req.getId());
        VosCustomerGroup update = new VosCustomerGroup();
        // 没有需要更新的，但是都更新了
        if (!BaseUtil.compare(base, target, update)) {
            return Response.data(true);
        }
        update.setId(target.getId());
        return Response.data(vosCustomerGroupService.updateById(update));
    }

    @PostMapping("/modifyGroupRelate")
    public Response<Boolean> modifyGroupRelate(@RequestBody ModifyGroupRelateReq req) {
        int accountId = getAccountId();
        if (Objects.nonNull(req.getDel()) && req.getDel()) {
            // 删除
            return Response.data(vosGroupRelateService.remove(accountId, req.getGroupId(), req.getCustomerId()));
        }
        // 新增
        return Response.data(vosGroupRelateService.addRelate(accountId, req.getGroupId(), req.getCustomerId()));
    }

    @PostMapping("/getGroupCustomerList")
    public Response<List<VosCustomerDTO>> getGroupCustomerList(@RequestBody IdReq req) {
        int groupId = req.getId();
        // 只可以查询自己的账号组
        if (!vosCustomerGroupService.isOwner(getAccountId(), groupId)) {
            throw BusinessException.create(FailedEnum.NEED_PERM);
        }
        List<Integer> customerIdList = vosGroupRelateService.getCustomerIdList(groupId);
        List<VosCustomer> customerList = vosCustomerService.getListByIds(customerIdList);
        return Response.data(VosWrapper.builder().entityCustomerDTO(customerList));
    }

    @PostMapping("/getCustomerList")
    public Response<List<VosCustomerDTO>> getCustomerList(@RequestBody GetCustomerReq req) {
        int accountId = getAccountId();
        // 查询其他账户客户数据需要权限
        if (Objects.nonNull(req.getAccountId())) {
            if (PermDataEnum.SHOW_ALL_CUSTOMER.verify(getToken())) {
                accountId = req.getAccountId();
            }
        }
        CustomerTypeEnum customerType = CustomerTypeEnum.getValueByCode(req.getType());
        List<VosCustomer> customerList = vosCustomerService.query(accountId, req.getServerId(), req.getVosKey(), customerType);
        Set<Integer> serverIds = new HashSet<>();
        for (VosCustomer customer : customerList) {
            serverIds.add(customer.getServerId());
        }
        Map<Integer, String> serverNameMap = vosServerService.getNameMap(serverIds);
        return Response.data(VosWrapper.builder().entityCustomerDTO(customerList, serverNameMap));
    }

    @PostMapping("/bindCustomer")
    public Response<VosCustomerDTO> bindCustomer(@RequestBody BindCustomerReq req) {
        if (!PermDataEnum.BIND_CUSTOMER.verify(getToken())) {
            throw BusinessException.create(FailedEnum.NEED_PERM);
        }
        String apiUrl = vosServerService.getApiUrl(req.getServerId());
        if (StringUtil.isBlank(apiUrl)) {
            throw BusinessException.create(FailedEnum.NOT_FOUND_VOS_SERVER);
        }
        VosCustomer vosCustomer = vosCustomerService.getByVosAccount(req.getServerId(), apiUrl, req.getVosAccount());
        // 返回结果用
        vosCustomer.setAccountId(req.getAccountId());
        // 保存
        VosCustomer update = new VosCustomer();
        update.setId(vosCustomer.getId());
        update.setAccountId(req.getAccountId());
        if (!vosCustomerService.updateById(update)) {
            throw BusinessException.create(FailedEnum.COMMON);
        }
        return Response.data(VosWrapper.builder().entityDTO(vosCustomer));
    }

    @PostMapping("/unbindCustomer")
    public Response<Boolean> unbindCustomer(@RequestBody IdReq req) {
        if (!PermDataEnum.BIND_CUSTOMER.verify(getToken())) {
            throw BusinessException.create(FailedEnum.NEED_PERM);
        }
        int id = req.getId();
        return Response.data(vosCustomerService.unbind(id));
    }

    @PostMapping("/modifyCustomer")
    public Response<Boolean> modifyCustomer(@RequestBody ModifyVosCustomerReq req) {
        // 修改时检测归属，不是该全用户的检测下权限
        if (Objects.nonNull(req.getId())) {
            if (!PermDataEnum.MODIFY_CUSTOMER.verify(getToken())) {
                if (!vosCustomerService.isOwner(getAccountId(), req.getId())) {
                    throw BusinessException.create(FailedEnum.NEED_PERM);
                }
            }
        }
        String apiUrl = vosServerService.getApiUrl(req.getServerId());
        if (StringUtil.isBlank(apiUrl)) {
            throw BusinessException.create(FailedEnum.NOT_FOUND_VOS_SERVER);
        }
        VosCustomer target = new VosCustomer();
        BaseUtil.set(target, req);
        if (Objects.nonNull(req.getValidTime())) {
            target.setValidTime(new Date(req.getValidTime()));
        }
        return Response.data(vosService.modifyCustomer(apiUrl, target));
    }

    @PostMapping("/recharge")
    public Response<Boolean> rechargeCustomer(@RequestBody RechargeReq req) {
        // 检查权限 是否可进行充值
        boolean canRecharge = PermDataEnum.RECHARGE.verify(getToken());
        if (!canRecharge) {
            throw BusinessException.create(FailedEnum.NEED_PERM);
        }
        String apiUrl = vosServerService.getApiUrl(req.getServerId());
        if (StringUtil.isBlank(apiUrl)) {
            throw BusinessException.create(FailedEnum.NOT_FOUND_VOS_SERVER);
        }
        VosCustomer vosCustomer = vosCustomerService.getByVosAccount(req.getServerId(), apiUrl, req.getVosAccount());
        if (vosCustomer.getAccountId() == 0) {
            throw BusinessException.create(FailedEnum.CHARGE_CUSTOMER_NEED_BIND);
        }
        if (!vosCustomer.getAccountId().equals(getAccountId())) {
            if (!PermDataEnum.RECHARGE_ALL.verify(getToken())) {
                // 无权限只能充值自己账号
                throw BusinessException.create(FailedEnum.CHARGE_CUSTOMER_NEED_BIND);
            }
        }
        PayDTO result = VosHelper.payCustomer(apiUrl, req.getVosAccount(), req.getMoney(), req.getComment());
        if (Objects.isNull(result)) {
            throw BusinessException.create(FailedEnum.COMMON);
        }
        VosCustomer updateCustomer = new VosCustomer()
                .setId(vosCustomer.getId())
                .setMoney(result.getMoney());
        vosCustomerService.updateById(updateCustomer);
        VosFeeLog feeLog = VosWrapper.builder().createFeeLog(FeeLogTypeEnum.RECHARGE, result.getPayMoney(),
                result.getMoney(), vosCustomer, req.getComment());
        return Response.data(vosFeeLogService.save(feeLog));
    }

    @PostMapping("/getFeeLogList")
    public Response<List<VosFeeLogDTO>> getFeeLogList(@RequestBody GetFeeLogReq req) {
        int accountId = getAccountId();
        // 查询其他账户客户数据需要权限
        if (PermDataEnum.SHOW_ALL_CUSTOMER.verify(getToken())) {
            if (Objects.nonNull(req.getAccountId())) {
                accountId = req.getAccountId();
            }
        }
        FeeLogTypeEnum feeLogType = FeeLogTypeEnum.getValueByCode(req.getType());
        List<VosFeeLog> vosFeeLogList = vosFeeLogService.query(feeLogType, accountId, req.getVosCustomerId(), req.getSize(), req.getIndex());
        Set<Integer> vosCustomerIdSet = new HashSet<>();
        for (VosFeeLog feeLog : vosFeeLogList) {
            vosCustomerIdSet.add(feeLog.getVosCustomerId());
        }
        Map<Integer, String> vosAccountMap = vosCustomerService.getVosAccountMap(vosCustomerIdSet);
        return Response.data(VosWrapper.builder().entityFeeLogDTO(vosFeeLogList, vosAccountMap));
    }

    @PostMapping("/getCallDetail")
    public Response<List<CallDetailDTO>> getCallDetail(@RequestBody GetCallDetailReq req) {
        VosServer vosServer = vosServerService.getById(req.getServerId());
        if (Objects.isNull(vosServer)) {
            throw BusinessException.create(FailedEnum.NOT_FOUND_VOS_SERVER);
        }
        if (RequestCacheHelper.hasVosCallDetail(req)) {
            return Response.data(RequestCacheHelper.getVosCallDetail(req));
        }
        List<CallDetailDTO> detailList = VosHelper.queryCallDetail(vosServer, new Date(req.getStartTime()), new Date(req.getEndTime()), req.getPhone());
        RequestCacheHelper.saveVosCallDetail(detailList, req);
        return Response.data(detailList);
    }


}
